package pl.jtb.ctl.tabory.ui.boe.ui.se;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;

import pl.jtb.ctl.tabory.dao.api.services.IStationService;
import pl.jtb.ctl.tabory.dao.data.vo.StationVO;
import pl.jtb.ctl.tabory.dao.impl.mybatis.servicemanager.ServiceManager;
import pl.jtb.ctl.tabory.ui.boe.osgi.Activator;
import pl.jtb.ctl.tabory.ui.boe.selection.StationSelection;
import pl.jtb.ctl.tabory.ui.editors.AbstractEditorPart;
import pl.jtb.ctl.tabory.ui.editors.EditorStateSL;
import pl.jtb.ctl.tabory.ui.selection.ISelectionListener;
import de.kupzog.ktable.KTable;
import de.kupzog.ktable.SWTX;

public class StationEditor extends AbstractEditorPart<StationSelection> {

    public static final String ID = "pl.jtb.ctl.tabory.ui.boe.ui.se.StationEditor";
    private final static Logger logger = Logger.getLogger(StationEditor.class);

    protected Action editorNewAction;
    protected Action editorEditAction;
    protected Action editorDeleteAction;
    private KTable table;
    private SampleModel model;

    public StationEditor() throws Exception {
        super();
    }

    @Override
    protected void createActions() {
        super.createActions();
        editorNewAction = new EditorActionNew();
        editorEditAction = new EditorActionEdit();
        editorDeleteAction = new EditorActionDelete();
        editorNewAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_NEW_WIZARD));
        editorEditAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
        editorDeleteAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_DELETE));
    }

    @Override
    public void createPartControl(Composite parent) {
        super.createPartControl(parent);
        form.getToolBarManager().removeAll();
        form.getToolBarManager().add(editorNewAction);
        form.getToolBarManager().add(editorEditAction);
        form.getToolBarManager().add(editorDeleteAction);
        form.getToolBarManager().add(new Separator());
        form.getToolBarManager().add(editorSaveAction);
        form.getToolBarManager().add(editorCancelAction);
        form.getToolBarManager().update(true);
    }

    @Override
    protected void initGui(Composite parent) {
        GridLayoutFactory.fillDefaults().numColumns(1).margins(5, 5).applyTo(form.getBody());
        Composite container = formToolkit.createComposite(form.getBody(), SWT.BORDER);
        GridLayoutFactory.fillDefaults().numColumns(2).applyTo(container);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(container);
        table = new KTable(container, SWTX.AUTO_SCROLL | SWTX.FILL_WITH_LASTCOL);
        model = new SampleModel(selection);
        table.setModel(model);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(table);
    }

    @Override
    protected void postInitGui(Composite parent) {
        model.addSelectionListener(new ISelectionListener<StationSelection>() {

            @Override
            public void selectionChanged(StationSelection selection) {
                table.redraw();
                setDirty(true);
            }
        });
    }

    @Override
    protected void doSave() throws Exception {
        IStationService stationService = ServiceManager.getInstance().getStationService();
        stationService.saveDistances(selection.getMapDistances());
        setDirty(false);
    }

    @Override
    protected void doCancel() throws Exception {
        selection = initSelection();
        model.setSelection(selection);
        table.redraw();
        setDirty(false);
    }

    private void doNew() throws Exception {
        InputDialog stationNameInputDialog = new InputDialog(getSite().getShell(), Activator.getMessage("stations.editor.dialogs.new.title"), Activator.getMessage("stations.editor.dialogs.new.message"), "", null);
        if (Window.OK == stationNameInputDialog.open()) {
            String stationName = stationNameInputDialog.getValue();
            StationVO storedStation = ServiceManager.getInstance().getStationService().getStation(stationName);
            if (storedStation != null) {
                MessageDialog.openError(getSite().getShell(), Activator.getMessage("stations.validation.save.notunique.title"), Activator.getMessage("stations.validation.save.notunique.message"));
                return;
            }
            StationVO station = new StationVO();
            station.setStationName(stationName);
            ServiceManager.getInstance().getStationService().saveUpdateStation(station);
            selection = initSelection();
            model.setSelection(selection);
            table.setModel(model);
            table.update();
        }
    }

    private void doEdit() throws Exception {
        List<String> listStationNames = new ArrayList<String>();
        for (StationVO station : selection.getListStations()) {
            listStationNames.add(station.getStationName());
        }
        ElementListSelectionDialog dialog = new ElementListSelectionDialog(getSite().getShell(), new LabelProvider());
        dialog.setElements(listStationNames.toArray());
        dialog.setTitle(Activator.getMessage("stations.editor.dialogs.edtid.title"));
        StationVO selectedStation = null;
        if (dialog.open() == Window.OK) {
            Object[] result = dialog.getResult();
            if (result.length > 0) {
                String selectedStationName = (String) result[0];
                selectedStation = selection.getListStations().get(listStationNames.indexOf(selectedStationName));
                InputDialog stationNameInputDialog = new InputDialog(getSite().getShell(), Activator.getMessage("stations.editor.dialogs.edtid.subdialog.title"), Activator.getMessage("stations.editor.dialogs.edtid.subdialog.message"),
                        selectedStationName, null);
                if (Window.OK == stationNameInputDialog.open()) {
                    String stationNewName = stationNameInputDialog.getValue();
                    if (stationNewName.equals(stationNewName)) {
                        StationVO storedStation = ServiceManager.getInstance().getStationService().getStation(stationNewName);
                        if (storedStation != null) {
                            MessageDialog.openError(getSite().getShell(), Activator.getMessage("stations.validation.save.notunique.title"), Activator.getMessage("stations.validation.save.notunique.message"));
                            return;
                        }
                    }
                    selectedStation.setStationName(stationNewName);
                    ServiceManager.getInstance().getStationService().saveUpdateStation(selectedStation);
                    selection = initSelection();
                    model.setSelection(selection);
                    table.setModel(model);
                    table.update();
                }
            }
        }
    }

    private void doDelete() throws Exception {
        List<String> listStationNames = new ArrayList<String>();
        for (StationVO station : selection.getListStations()) {
            listStationNames.add(station.getStationName());
        }
        ElementListSelectionDialog dialog = new ElementListSelectionDialog(getSite().getShell(), new LabelProvider());
        dialog.setElements(listStationNames.toArray());
        dialog.setTitle(Activator.getMessage("stations.editor.dialogs.delete.title"));
        if (dialog.open() == Window.OK) {
            Object[] result = dialog.getResult();
            if (result.length > 0) {
                MessageBox messageBox = new MessageBox(getSite().getShell(), SWT.ICON_QUESTION | SWT.YES | SWT.NO);
                messageBox.setMessage(Activator.getMessage("stations.editor.dialogs.delete.confirm.message"));
                messageBox.setText(Activator.getMessage("stations.editor.dialogs.delete.confirm.title"));
                int confirmation = messageBox.open();
                if (confirmation == SWT.YES) {
                    String selectedStationName = (String) result[0];
                    StationVO selectedStation = selection.getListStations().get(listStationNames.indexOf(selectedStationName));
                    ServiceManager.getInstance().getStationService().delecteStation(selectedStation);
                    selection = initSelection();
                    model.setSelection(selection);
                    table.setModel(model);
                    table.update();
                }
            }
        }
    }

    @Override
    protected StationSelection initSelection() throws Exception {
        StationSelection selection = new StationSelection();
        selection.setEditorState(EditorStateSL.CLEAN);
        List<StationVO> listStations = ServiceManager.getInstance().getStationService().getAllStations();
        Map<StationVO, Map<StationVO, Double>> mapDistances = ServiceManager.getInstance().getStationService().getAllDistances();
        selection.setListStations(listStations);
        selection.setMapDistances(mapDistances);
        return selection;
    }

    @Override
    public void setFocus() {
        // TODO Auto-generated method stub

    }

    private class EditorActionNew extends Action {
        @Override
        public void run() {
            logger.debug("Run menu action: new element.");
            BusyIndicator.showWhile(form.getDisplay(), new Runnable() {
                @Override
                public void run() {
                    try {
                        doNew();
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                        openErrorDialog(e);
                    }
                }

            });
        }
    }

    private class EditorActionEdit extends Action {
        @Override
        public void run() {
            logger.debug("Run menu action: edit element.");
            BusyIndicator.showWhile(form.getDisplay(), new Runnable() {
                @Override
                public void run() {
                    try {
                        doEdit();
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                        openErrorDialog(e);
                    }
                }

            });
        }
    }

    private class EditorActionDelete extends Action {
        @Override
        public void run() {
            logger.debug("Run menu action: delete element.");
            BusyIndicator.showWhile(form.getDisplay(), new Runnable() {
                @Override
                public void run() {
                    try {
                        doDelete();
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                        openErrorDialog(e);
                    }
                }

            });
        }
    }

}
